%%% ------------------------------------------------------------------
%%% Licensed under the Apache License, Version 2.0 (the 'License');
%%%  you may not use this file except in compliance with the License.
%%%  You may obtain a copy of the License at
%%%
%%%      http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Copyright (c) 2017 dwg <bypf2009@vip.qq.com>
%%%
%%%  Unless required by applicable law or agreed to in writing, software
%%%  distributed under the License is distributed on an 'AS IS' BASIS,
%%%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%%  See the License for the specific language governing permissions and
%%%  limitations under the License.
%%%
%%% @doc  获取域名列表
%%% @author  dwg <'bypf2009@vip.qq.com'>
%%% @copyright 2017 dwg <bypf2009@vip.qq.com>
%%% @reference https://help.aliyun.com/document_detail/29751.html
%%% @end
%%% created|changed : 2017-02-09 15:14
%%% coding : utf-8
%%% ------------------------------------------------------------------
-module(domain_api).

-export([describe_domains/2, describe_domains/3]).
-export([add_domain_record/3, delete_domain_record/3]).
-export([describe_domains_records/3, describe_domains_record_info/3,
         describe_sub_domains_records/3, update_domain_record/3]).
-export([post_response/2, get_response/1]).

-author("dwg").

-include("domain.hrl").

-define(METHOD_DEFAULT, <<"GET">>).
-define(ACTION, #{<<"Action">> => <<"DescribeDomains">>}).


% 名称             类型 是否必须    描述
%%-----------------------------------------------------------------
% Action        String  是       操作接口名，系统规定参数，取值：DescribeDomains
% PageNumber    Long    否       当前页数，起始值为1，默认为1
% PageSize      Long    否       分页查询时设置的每页行数，最大值100，默认为20
% KeyWord       String  否       关键字，按照”%KeyWord%”模式搜索，不区分大小写
% GroupId       String  否       域名分组ID，如果不填写则默认为全部分组


%%@doc 获取域名列表 DescribeDomains
describe_domains(AccessKeyId, AccessKeySecret) ->
    describe_domains(AccessKeyId, AccessKeySecret, ?ACTION).

%%@doc 获取域名列表 DescribeDomains
-spec describe_domains(AccessKeyId, AccessKeySecret, ParamsExtra) -> Response when
        AccessKeyId :: iodata(),
        AccessKeySecret :: iodata(),
        ParamsExtra :: maps:map(),
        Response :: any().
describe_domains(AccessKeyId, AccessKeySecret, ParamsExtra) when is_map(ParamsExtra) ->
    Path = make_path(<<"DescribeDomains">>, AccessKeyId, AccessKeySecret, ParamsExtra),
    case mguns:gun_get(Path) of
        {_, _, Body} ->
            jiffy:decode(Body, [return_maps]);
        {error, Reason} ->
            {error, Reason}
    end.

%%@doc 获取解析记录列表
-spec describe_domains_records(AccessKeyId, AccessKeySecret, ParamsExtra) -> Response when
        AccessKeyId :: iodata(),
        AccessKeySecret :: iodata(),
        ParamsExtra :: maps:map(),
        Response :: any().
describe_domains_records(AccessKeyId, AccessKeySecret, ParamsExtra) ->
    Path = make_path(<<"DescribeDomainRecords">>, AccessKeyId, AccessKeySecret, ParamsExtra),
    get_response(Path).

%%@doc 获取解析记录信息
-spec describe_domains_record_info(AccessKeyId, AccessKeySecret, ParamsExtra) -> Response when
        AccessKeyId :: iodata(),
        AccessKeySecret :: iodata(),
        ParamsExtra :: maps:map(),
        Response :: any().
describe_domains_record_info(AccessKeyId, AccessKeySecret, ParamsExtra) ->
    Path = make_path(<<"DescribeDomainRecordInfo">>, AccessKeyId, AccessKeySecret, ParamsExtra),
    get_response(Path).

%%@doc 获取子域名的解析记录列表
-spec describe_sub_domains_records(AccessKeyId, AccessKeySecret, ParamsExtra) -> Response when
        AccessKeyId :: iodata(),
        AccessKeySecret :: iodata(),
        ParamsExtra :: maps:map(),
        Response :: any().
describe_sub_domains_records(AccessKeyId, AccessKeySecret, ParamsExtra) ->
    Path = make_path(<<"DescribeSubDomainRecords">>, AccessKeyId, AccessKeySecret, ParamsExtra),
    get_response(Path).

%%@doc 添加解析记录
-spec add_domain_record(AccessKeyId, AccessKeySecret, ParamsExtra) -> Response when
        AccessKeyId :: iodata(),
        AccessKeySecret :: iodata(),
        ParamsExtra :: maps:map(),
        Response :: any().
add_domain_record(AccessKeyId, AccessKeySecret, ParamsExtra) ->
    Body = make_path(<<"AddDomainRecord">>, AccessKeyId, AccessKeySecret, ParamsExtra),
    post_response("/", Body).

%%@doc 删除解析记录
-spec delete_domain_record(AccessKeyId, AccessKeySecret, ParamsExtra) -> Response when
        AccessKeyId :: iodata(),
        AccessKeySecret :: iodata(),
        ParamsExtra :: maps:map(),
        Response :: any().
delete_domain_record(AccessKeyId, AccessKeySecret, ParamsExtra) ->
    Body = make_path(<<"DeleteDomainRecord">>, AccessKeyId, AccessKeySecret, ParamsExtra),
    post_response("/", Body).

%%@doc 修改解析记录
-spec update_domain_record(AccessKeyId, AccessKeySecret, ParamsExtra) -> Response when
        AccessKeyId :: iodata(),
        AccessKeySecret :: iodata(),
        ParamsExtra :: maps:map(),
        Response :: any().
update_domain_record(AccessKeyId, AccessKeySecret, ParamsExtra) ->
    Body = make_path(<<"UpdateDomainRecord">>, AccessKeyId, AccessKeySecret, ParamsExtra),
    post_response("/", Body).

%%% ------------------------------------------------------------------
%%%  Lib
%%% ------------------------------------------------------------------

%%@private 过滤参数
params_struct(ParamsExtra, FilterKeys) ->
    lists:foldl(
        fun (Key, Map) ->
            case maps:find(Key, ParamsExtra) of
                {ok, Val} -> Map#{Key => Val};
                error     -> Map
            end
        end, #{}, FilterKeys).

%%@private 构造api参数
make_path(<<"DescribeDomains">>, AccessKeyId, AccessKeySecret, ParamsExtra) ->
    make_body(AccessKeyId, AccessKeySecret, ParamsExtra,
              <<"GET">>, <<"DescribeDomains">>, ?DES_DOMAIN);

make_path(<<"DescribeDomainRecords">>, AccessKeyId, AccessKeySecret, ParamsExtra) ->
    make_body(AccessKeyId, AccessKeySecret, ParamsExtra,
              <<"GET">>, <<"DescribeDomainRecords">>, ?DES_DOMAIN_RECORD);

make_path(<<"DescribeDomainRecordInfo">>, AccessKeyId, AccessKeySecret, ParamsExtra) ->
    make_body(AccessKeyId, AccessKeySecret, ParamsExtra,
              <<"GET">>, <<"DescribeDomainRecordInfo">>, ?DES_DOMAIN_RECORD_INFO);

make_path(<<"DescribeSubDomainRecords">>, AccessKeyId, AccessKeySecret, ParamsExtra) ->
    make_body(AccessKeyId, AccessKeySecret, ParamsExtra,
              <<"GET">>, <<"DescribeSubDomainRecords">>, ?DES_SUB_DOMAIN_RECORD_INFO);

make_path(<<"AddDomainRecord">>, AccessKeyId, AccessKeySecret, ParamsExtra) ->
    make_body(AccessKeyId, AccessKeySecret, ParamsExtra,
              <<"POST">>, <<"AddDomainRecord">>, ?ADD_DOMAIN_RECORD);

make_path(<<"DeleteDomainRecord">>, AccessKeyId, AccessKeySecret, ParamsExtra) ->
    make_body(AccessKeyId, AccessKeySecret, ParamsExtra,
              <<"POST">>, <<"DeleteDomainRecord">>, ?DELETE_DOMAIN_RECORD);

make_path(<<"UpdateDomainRecord">>, AccessKeyId, AccessKeySecret, ParamsExtra) ->
    make_body(AccessKeyId, AccessKeySecret, ParamsExtra,
              <<"POST">>, <<"UpdateDomainRecord">>, ?UPDATE_DOMAIN_RECORD);

make_path(_Action, _AccessKeyId, _AccessKeySecret, _ParamsExtra) ->
    io:format("unkown action:~p, KeyId:~p, KeySecret:~p, Params~p.~n", [
        _Action, _AccessKeyId, _AccessKeySecret, _ParamsExtra]),
    error.

%%@private body
make_body(AccessKeyId, AccessKeySecret, ParamsExtra, Method, Action, FilterKeys) ->
    ParamsExtraEncode1 = params_struct(ParamsExtra, FilterKeys),
    ParamsExtraEncode2 = ParamsExtraEncode1#{<<"Action">> => Action},
    PramasPublic = pub_params:params(AccessKeyId, AccessKeySecret, Method, ParamsExtraEncode2),
    Params = maps:merge(PramasPublic, ParamsExtraEncode2),
    ali_uri:to_uri(Params).

%%@private 返回值
get_response(Path) ->
    case mguns:gun_get(Path) of
        {_, _, Body} ->
            jiffy:decode(Body, [return_maps]);
        {error, Reason} ->
            {error, Reason}
    end.

post_response(Path, Data) ->
    case mguns:gun_post(Path, Data) of
        {_, _, Body} ->
            jiffy:decode(Body, [return_maps]);
        {error, Reason} ->
            {error, Reason}
    end.
